import {
  AfterViewInit,
  Directive, ElementRef, Host, Input, OnChanges, OnDestroy, OnInit, Optional, Renderer2,
} from '@angular/core';

import { ApesUpdateHostClassService } from '../core/services/update-host-class.service';
import { Subject } from 'rxjs';
import { isNotNil } from '@shared/apes/core/util/check';
import { ApesRowDirective } from '@shared/apes/grid/apes-row.directive';
import { startWith, takeUntil } from 'rxjs/operators';

export interface EmbeddedProperty {
  span: number;
  pull: number;
  push: number;
  offset: number;
  order: number;
}
@Directive({
  selector : '[apes-col],apes-col',
  providers: [ ApesUpdateHostClassService ]
})
export class ApesColDirective implements OnInit, OnChanges, AfterViewInit, OnDestroy{private el: HTMLElement = this.elementRef.nativeElement;
  private prefixCls = 'apes-col';
  protected destroy$ = new Subject();

  @Input() apesSpan: number;
  @Input() apesOrder: number;
  @Input() apesOffset: number;
  @Input() apesPush: number;
  @Input() apesPull: number;
  @Input() apesXs: number | EmbeddedProperty;
  @Input() apesSm: number | EmbeddedProperty;
  @Input() apesMd: number | EmbeddedProperty;
  @Input() apesLg: number | EmbeddedProperty;
  @Input() apesXl: number | EmbeddedProperty;
  @Input() apesXXl: number | EmbeddedProperty;

  /** temp solution since no method add classMap to host https://github.com/angular/angular/issues/7289*/
  setClassMap(): void {
    const classMap = {
      [ `${this.prefixCls}-${this.apesSpan}` ]         : isNotNil(this.apesSpan),
      [ `${this.prefixCls}-order-${this.apesOrder}` ]  : isNotNil(this.apesOrder),
      [ `${this.prefixCls}-offset-${this.apesOffset}` ]: isNotNil(this.apesOffset),
      [ `${this.prefixCls}-pull-${this.apesPull}` ]    : isNotNil(this.apesPull),
      [ `${this.prefixCls}-push-${this.apesPush}` ]    : isNotNil(this.apesPush),
      ...this.generateClass()
    };
    this.updateHostClassService.updateHostClass(this.el, classMap);
  }

  generateClass(): object {
    const listOfSizeInputName = [ 'apesXs', 'apesSm', 'apesMd', 'apesLg', 'apesXl', 'apesXXl' ];
    const listClassMap = {};
    listOfSizeInputName.forEach(name => {
      const sizeName = name.replace('apes', '').toLowerCase();
      if (isNotNil(this[ name ])) {
        if ((typeof (this[ name ]) === 'number') || (typeof (this[ name ]) === 'string')) {
          listClassMap[ `${this.prefixCls}-${sizeName}-${this[ name ]}` ] = true;
        } else {
          listClassMap[ `${this.prefixCls}-${sizeName}-${this[ name ].span}` ] = this[ name ] && isNotNil(this[ name ].span);
          listClassMap[ `${this.prefixCls}-${sizeName}-pull-${this[ name ].pull}` ] = this[ name ] && isNotNil(this[ name ].pull);
          listClassMap[ `${this.prefixCls}-${sizeName}-push-${this[ name ].push}` ] = this[ name ] && isNotNil(this[ name ].push);
          listClassMap[ `${this.prefixCls}-${sizeName}-offset-${this[ name ].offset}` ] = this[ name ] && isNotNil(this[ name ].offset);
          listClassMap[ `${this.prefixCls}-${sizeName}-order-${this[ name ].order}` ] = this[ name ] && isNotNil(this[ name ].order);
        }
      }

    });
    return listClassMap;
  }

  constructor(private updateHostClassService: ApesUpdateHostClassService,
              private elementRef: ElementRef,
              @Optional() @Host() public apesRowDirective: ApesRowDirective,
              public renderer: Renderer2
  ) {
  }

  ngOnChanges(): void {
    this.setClassMap();
  }

  ngAfterViewInit(): void {
    if (this.apesRowDirective) {
      this.apesRowDirective.actualGutter$.pipe(
        startWith(this.apesRowDirective.actualGutter),
        takeUntil(this.destroy$)
      ).subscribe((actualGutter) => {
        this.renderer.setStyle(this.el, 'padding-left', `${actualGutter / 2}px`);
        this.renderer.setStyle(this.el, 'padding-right', `${actualGutter / 2}px`);
      });
    }
  }

  ngOnInit(): void {
    this.setClassMap();
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
